<template>
  <div class="layout-container">
    <el-card shadow="Never" class="card">
      <div class="header-container">
        <el-select v-model="selectedLanguage" @change="updateLanguage" class="select" size="default">
          <el-option
              v-for="option in options"
              :key="option.value"
              :label="option.label"
              :value="option.value">
          </el-option>
        </el-select>
        <div class="button-container">
          <el-button size="large" round class="run-button" @click="aiAnalysisCode">
            <img src="../../assets/aiCode.svg" alt="aiCode" class="button-icon">Ai分析
          </el-button>
          <template v-if="showInput">
            <el-input v-model="inputContent" placeholder="请输入内容" class="input-box"></el-input>
          </template>
          <template v-else>
            <el-button size="large" round @click="toggleInput">
              <img src="../../assets/input.svg" alt="Search" class="button-icon"> 输入
            </el-button>
          </template>
          <el-button
              size="large"
              round
              class="run-button"
              :loading="isRunning"
              :disabled="isRunning"
              @click="executeCode"
          >
            <img v-if="!isRunning" src="../../assets/start.svg" alt="Run" class="button-icon">
            {{ isRunning ? '正在运行中...' : '运行' }}
          </el-button>
        </div>
      </div>
      <el-divider/>
      <div ref="editContainer" class="code-editor"></div>
    </el-card>
    <el-card shadow="never" style="min-height: 16vh; font-size: 14px">
      <template #header>
        <div class="card-header" style="font-weight: 700;font-size: 14px">
          <span>运行结果(控制台)</span>
        </div>
      </template>
      <pre :style="{ color: outputColor, maxHeight: '16vh', overflowY: 'auto' }">{{ output }}</pre>
    </el-card>
    <el-dialog
        v-model="analysisCodeDialogVisible"
        title="Ai分析结果"
        width="650"
    >
      <span v-html="aiAnswer"></span>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="analysisCodeDialogVisible = false" class="confirm-btn">知道了</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import axios from 'axios';
import {getCurrentInstance, onMounted, nextTick, ref} from 'vue';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.main.js';
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
import {API_BASE_URL} from '@/config.ts';
import hljs from "highlight.js";
import 'highlight.js/styles/docco.css';
import {ElMessage} from "element-plus";
import {fetchEventSource} from "@microsoft/fetch-event-source";

export default {
  props: {
    value: String,
  },
  setup(props, {emit}) {
    const selectedLanguage = ref('C++');
    const showInput = ref(false);
    const inputContent = ref('');
    let monacoEditor = null;
    const output = ref('');
    const outputVisible = ref(false);
    const {proxy} = getCurrentInstance();
    const outputColor = ref('black');
    const token = localStorage.getItem('token');
    const isRunning = ref(false);
    const analysisCodeDialogVisible = ref(false);
    const aiAnswer = ref('');

    // Fetch the initial code when the component is mounted
    onMounted(async () => {
      await nextTick();

      try {
        const response = await axios.get(`${API_BASE_URL}/userCode/webCode`, {
          headers: { 'token': token }
        });

        let code;
        let language;

        if (response.data.code === 0) {
          code = response.data.data.code;
          language = response.data.data.language;
          console.log("language:"+language)
          // 直接赋值给响应式变量 selectedLanguage.value
          const languageMap = {
            "cpp": "cpp",
            "java": "Java",
            "python": "Python3",
            "c": "C",
          };
          // 根据选择的语言获取对应的格式
          selectedLanguage.value = languageMap[language] || 'cpp';
        } else {
          console.log("No code fetched");
          code = '// 请输入代码';

          // 如果没有获取到语言，设置默认值
          language = selectedLanguage.value === 'C++' ? 'cpp' : selectedLanguage.value;
        }

        // 初始化 Monaco Editor
        monacoEditor = monaco.editor.create(proxy.$refs.editContainer, {
          value: code,
          readOnly: false,
          language: language,
          theme: 'vs',
          selectOnLineNumbers: true,
          renderSideBySide: false
        });

      } catch (error) {
        console.error("Failed to fetch code:", error);
      }


      monacoEditor.onDidChangeModelContent(() => {
        const currentValue = monacoEditor?.getValue();
        emit('update:value', currentValue);

        // Call the POST request to save the code
        saveCodeToServer(currentValue);
      });
    });

    // POST request to save code to the server
    const saveCodeToServer = async (newCode) => {
      try {
        // 创建请求数据
        const requestData = {
          code: newCode,
          language: selectedLanguage.value
        };
        console.log("selectedLanguage.value:"+selectedLanguage.value)
        // 发送 POST 请求
        await axios.post(`${API_BASE_URL}/userCode/webCode`, requestData, {
          headers: {
            'token': token,
            'Content-Type': 'application/json; charset=UTF-8',
          }
        });
        console.log("代码和语言保存成功。");
      } catch (error) {
        console.error("保存代码失败：", error);
      }
    };



    const toggleInput = () => {
      showInput.value = !showInput.value;
    };

    const aiAnalysisCode = () => {
      aiAnswer.value = '';

      if (monacoEditor.getValue().length < 20) {
        ElMessage.error('代码太短了，再写点吧！');
        return;
      }

      analysisCodeDialogVisible.value = true;

      let answer = '';
      let nowHtml = '';

      setInterval(async () => {
        if (nowHtml.length > aiAnswer.value.length) {
          let nowLen = aiAnswer.value.length;
          if (nowHtml[nowLen] === '<') {
            while (nowHtml[nowLen] !== '>') {
              nowLen++;
            }
          }
          aiAnswer.value = nowHtml.slice(0, nowLen + 1);
        }
      }, 70);

      const controller = new AbortController();

      fetchEventSource(`${API_BASE_URL}/ai/analysisCode`, {
        method: 'POST',
        headers: {
          'content-type': 'application/json',
          'token': token,
        },
        body: JSON.stringify({
          code: monacoEditor.getValue(),
          language: selectedLanguage.value,
          oiString: showInput.value ? inputContent.value : ""
        }),
        signal: controller.signal,
        openWhenHidden: true,
        onmessage(event) {
          answer = answer.concat(event.data);
          if (event.data === '&#92n[DONE]') {
            controller.abort();
            return;
          }
          nowHtml = answer;
        },
        onclose() {
          controller.abort();
        },
        onerror() {
          controller.abort();
        }
      });
    };

    const executeCode = async () => {
      console.log("isRunning:"+isRunning.value)
      // 设置为运行中状态
      isRunning.value = true;
      console.log("isRunning:"+isRunning.value)
      let language = selectedLanguage.value;
      language = language === "cpp" ? "C++" : language;

      const codeData = {
        code: monacoEditor.getValue(),
        language: language,
        oiString: showInput.value ? inputContent.value : ""
      };

      try {
        const response = await axios.post(`${API_BASE_URL}/commit/oi`, codeData, {
          headers: { 'token': token }
        });
        console.log(response)
        if(response.data.code===1){ alert('请登录以后提交代码！');return}

        if (response.data.code === 502) {
          output.value = response.data.msg;
          outputColor.value = 'red';
        } else {
          const result = response.data.data.data[0];
          output.value = result && result.files ? result.files.stdout : '没有输出';
          outputColor.value = 'black';
        }
        outputVisible.value = true;
      } catch (error) {
        console.error('请求错误', error);
        alert('执行错误，请检查网络或联系管理员。');
      } finally {
        // 恢复按钮状态
        isRunning.value = false;
      }
    };

    return {
      aiAnswer,
      analysisCodeDialogVisible,
      output,
      outputVisible,
      selectedLanguage,
      showInput,
      inputContent,
      isRunning,
      outputColor,
      options: [
        {label: "C++", value: 'cpp'},
        {label: 'C', value: 'c'},
        {label: 'Python3', value: 'python'},
        {label: 'Java', value: 'java'}
      ],
      updateLanguage: () => {
        monaco.editor.setModelLanguage(monacoEditor.getModel(), selectedLanguage.value);
      },
      toggleInput,
      executeCode,
      aiAnalysisCode
    };
  }
};
</script>



<style scoped>
.layout-container {
  display: flex;
  flex-direction: column;
}

.header-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}

.select {
  width: 100px;
}

.code-editor {
  width: 100%;
  height: 55vh;
}

.button-container {
  display: flex;
  justify-content: space-between;
}

.button-icon {
  height: 2.2vh;
  margin-right: 5px;
}

.card {
  width: 100%;
  height: 60vh;
  margin-top: 2.5vh;
}

.input-box {
  width: 200px;
}
</style>
